using System;
using UnityEngine;
using Object = UnityEngine.Object;

namespace Framework.Timer
{
    /// <summary>
    /// 计时器Handler，延迟指定时间后触发callback
    /// </summary>
    public sealed class TimeHandler
    {
        private float         _maxTime;//计时时间
        private float         _delayTime;//当前时间
        private Action        _onComplete;//完成时调用方法
        private Action<float> _onUpdate;//计时时调用方法
        private GameObject    _gameObject;//方法所对应组件
        private bool          _isMono;//是否挂载在mono上
        private bool          _isPause;//计时是否暂停
        private bool          _hasFramePlayer;
        public   bool IsDone    => this._delayTime >= this._maxTime;//是否完成计时
        public   bool IsPlaying => !IsDone && !this._isKill;//是否在计时中
        
        internal bool _isKill;//是否关闭
        /// <summary>
        /// 一般方法的计时器
        /// </summary>
        /// <param name="delay">延时时间</param>
        /// <param name="callback">回调方法</param>
        /// <param name="onUpdate">在计时过程中需调用方法</param>
        internal TimeHandler(float delay, Action callback, Action<float> onUpdate = null)
        {
            this._maxTime    = delay;
            this._delayTime  = 0;
            this._onComplete = callback;
            this._onUpdate   = onUpdate;
            this._isMono     = false;
            this._isKill     = false;
        }
        internal TimeHandler(float delay, bool hasFramePlayer, Action callback, Action<float> onUpdate = null)
        {
            this._maxTime = delay;
            this._delayTime = 0;
            this._onComplete = callback;
            this._onUpdate = onUpdate;
            this._isMono = false;
            this._isKill = false;
            this._hasFramePlayer = hasFramePlayer;
        }
        /// <summary>
        /// 挂载在mono上的计时器
        /// </summary>
        /// <param name="gameObject">组件</param>
        /// <param name="delay">延时时间</param>
        /// <param name="callback">回调方法</param>
        /// <param name="onUpdate">在计时过程中需调用方法</param>
        internal TimeHandler(GameObject gameObject, float delay, Action callback, Action<float> onUpdate = null)
        {
            this._maxTime    = delay;
            this._delayTime  = 0;
            this._onComplete = callback;
            this._onUpdate   = onUpdate;
            this._gameObject = gameObject;
            this._isMono     = true;
            this._isKill     = false;
        }
        /// <summary>
        /// 计时并调用（由于并没有挂载在mono上，Update只是一般方法）
        /// </summary>
        internal void Update()
        {
            if (!this.IsDone)
            {   
                //是否是挂在在MonoBehavior上
                if (this._isMono)
                {
                    //若是则每次都需进行判定，若组件为空则退出计时
                    if (ReferenceEquals(this._gameObject,null))
                    {
                        this.Kill();
                    }
                }
                //计时是否暂停
                if (!this._isPause)
                {       
                    this._onUpdate?.Invoke(this._delayTime / this._maxTime);//如果onUpdate方法存在，则传入当前时间/延时时间（进度值:0-1）
                    this._delayTime += Time.deltaTime;//若没有暂停，则开始计时
                }

                //计时是否完成
                if (this.IsDone)
                {
                    this._onComplete?.Invoke();
                }
            }
        }
        /// <summary>
        /// 关闭计时器
        /// </summary>
        public void Kill()
        {
            // this._delayTime = this._maxTime;
            this._isKill = true;
        }
        /// <summary>
        /// 暂停计时器
        /// </summary>
        /// <param name="b"></param>
        public void Pause(bool b)
        {
            this._isPause = b;
        }
    }
}